import enum

from sqlalchemy import func

from core.file.helpers import get_signed_file_url
from .engine import db
from .types import StringUUID
class SysMenuType(enum.StrEnum):
    DIR = 'D'
    MENU = 'M'
    BUTTON = 'B'
    API = 'A'
    @staticmethod
    def choices()->list[str]:
        return ["D","M","B","A"]
    @staticmethod
    def ROUTER_TYPES()->list[str]:
        return ["D","M"]

class SysMenu(db.Model):
    __tablename__ = "sys_menus"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sys_menus_pkey"),
        db.UniqueConstraint("tenant_id","name",name="sys_menus_name_idx"),
        db.UniqueConstraint("tenant_id","perms", name="sys_menus_perms_idx"),
    )
    id = db.Column(StringUUID,primary_key =True, server_default=db.text("uuid_generate_v4()"))
    tenant_id = db.Column(StringUUID, nullable=False)
    parent_id = db.Column(StringUUID, nullable=True)
    name = db.Column(db.String(64), nullable=False)
    url = db.Column(db.String(255), nullable=True)
    perms = db.Column(db.String(512), nullable=True)
    menu_type = db.Column(db.String(1), nullable=False, server_default=db.text("'M'::character varying"))
    # icon_file_id = db.Column(StringUUID, nullable=True)
    icon = db.Column(db.String(255), nullable=True)
    component = db.Column(db.String(128), nullable=True)
    is_inner = db.Column(db.Boolean, nullable=False, server_default=db.text("false"),comment="是否内置功能")
    seq = db.Column(db.Integer, nullable=True)
    created_at = db.Column(db.DateTime, nullable=False, server_default=db.text("CURRENT_TIMESTAMP"))
    created_by = db.Column(StringUUID, nullable=False)
    def to_dict(self):
        return {
            "id": self.id,
            "name": self.name,
            "perms": self.perms,
            "path": self.url,
            "menu_type":self.menu_type,
            "component": self.component,
            "is_inner": self.is_inner,
            "seq": self.seq,
            "children": []
        }


class SysRole(db.Model):
    __tablename__ = "sys_roles"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sys_roles_pkey"),
        db.Index("sys_roles_name_idx", "name"),
        db.Index("sys_roles_tenant_id_idx","tenant_id"),
        db.UniqueConstraint("tenant_id","name", name="sys_roles_name_key"),
    )
    id = db.Column(StringUUID, server_default=db.text("uuid_generate_v4()"))
    tenant_id = db.Column(StringUUID, nullable=False)
    name = db.Column(db.String(32), nullable=False)
    code = db.Column(db.String(32), nullable=False)
    remark = db.Column(db.String(255), nullable=True)
    is_inner = db.Column(db.Boolean, nullable=False, server_default=db.text("false"),comment="是否内置角色")
    created_at = db.Column(db.DateTime, nullable=False, server_default=func.current_timestamp())
    created_by = db.Column(StringUUID, nullable=False)
    updated_at = db.Column(db.DateTime, nullable=True)
    updated_by = db.Column(StringUUID, nullable=True)
    @property
    def perms(self)->list[str]:
        results = db.session.query(SysMenu.perms).join(SysRoleMenu,(SysRoleMenu.menu_id==SysMenu.id)&(SysRoleMenu.role_id==self.id)).all()
        return [result[0] for result in results if result] if results else []
    
    @property
    def routers(self)->list[SysMenu]:
        results = db.session.query(SysMenu).join(SysRoleMenu,(SysRoleMenu.menu_id==SysMenu.id)&(SysRoleMenu.role_id==self.id))\
                    .filter(SysMenu.menu_type.in_(SysMenuType.ROUTER_TYPES())).all()
        return results if results else []

class SysRoleMenu(db.Model):
    __tablename__ = "sys_role_menus"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sys_role_menus_pkey"),
        db.Index("sys_role_menus_role_id_idx", "role_id"),
        db.Index("sys_role_menus_menu_id_idx", "menu_id"),
    )
    id = db.Column(db.BigInteger, nullable=False,autoincrement=True,primary_key=True)
    role_id = db.Column(StringUUID, nullable=False)
    menu_id = db.Column(StringUUID, nullable=False)

class SysAccountRole(db.Model):
    __tablename__ = "sys_account_roles"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sys_account_role_pkey"),
        db.Index("sys_account_role_account_id_idx","tenant_id","account_id"),
        db.Index("sys_account_role_role_id_idx", "role_id"),
        db.UniqueConstraint("account_id", "role_id", name="unique_sys_account_role"),
    )
    id = db.Column(db.BigInteger(),autoincrement=True, primary_key=True,)#server_default=db.text("nextval('sys_account_roles_id_seq'::regclass)"))
    tenant_id = db.Column(StringUUID, nullable=False)
    account_id = db.Column(StringUUID, nullable=False)
    role_id = db.Column(StringUUID, nullable=False)
